#pragma once
#include<string>

#include"noncopyable.h"

// 定义宏，方便用户使用
// logger.setLogLevel(INFO); 防止错误，宏函数采用do.. while 形式 
// snprintf(buf,1024,logmsgFormat,##__VA_ARGS__) 这个打印可以指定缓冲区，并且通过宏拿到可变参。
#define LOG_INFO(logmsgFormat,...) \
    do  \
    {\
        Logger &logger = Logger::instance(); \
        logger.setLogLevel(INFO);\
        char buff[1024] = {0};\
        snprintf(buff, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buff);\
    }while(0)

// Logger &logger防止错误，宏函数采用do.. while 形式
// snprintf这个打印可以指定缓冲区，并且通过宏拿到可变参。
#define LOG_ERROR(logmsgFormat,...) \
    do  \
    {\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(ERROR);\
        char buff[1024] = {0};\
        snprintf(buff,1024,logmsgFormat,##__VA_ARGS__);\
        logger.log(buff);\
    }while(0)

#define LOG_FATAL(logmsgFormat,...) \
    do  \
    {\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(FATAL);\
        char buff[1024] = {0};\
        snprintf(buff,1024,logmsgFormat,##__VA_ARGS__);\
        logger.log(buff);\
        exit(-1);\
    }while(0)

// 默认是关闭的
#ifdef MUDEBUG
#define LOG_DEBUG(logmsgFormat,...) \
    do  \
    {\
        Logger &logger = Logger::instance();\
        logger.setLogLevel(DEBUG);\
        char buff[1024] = {0};\
        snprintf(buff,1024,logmsgFormat,##__VA_ARGS__);\
        logger.log(buff);\
    }while(0)
#else
    #define LOG_DEBUG(logmsgFormat,...)
#endif
// 定义日志的级别 INFO ERROR FATAL DEBUG
enum LogLevel
{
    INFO, // 普通信息
    ERROR, // 错误信息
    FATAL, // Core 信息
    DEBUG, //调试信息
};

// 输出一个日志类,单例类
class Logger:noncopyable
{
public:
    static Logger& instance();// 获取日志唯一的实例对象
    // 设置日志级别
    void setLogLevel(int level);
    // 写日志
    void log(std::string msg);
private:
    int logLevel_; // 前_ 系统级别变量可能产生冲突！，所以用后_;
    Logger(){}
};
